/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

#ifndef __G_BLENDER_FACE__
#define __G_BLENDER_FACE__

#include "GPrerequisites.h"

#include "MathUtil.h"
#include "BlenderMeshUtil.h"
#include "MeshVertex.h"

namespace GNgine
{
	class MeshFaceIndex
	{
	public:
		int v1, v2, v3;//indices into vertex buffer
	public:
		MeshFaceIndex();
		MeshFaceIndex(const MeshFaceIndex& o);
		MeshFaceIndex& operator= (const MeshFaceIndex& o);
	};


	//MeshFace is a triangle face
	class MeshFace
	{
	public:
		MeshVertex v0;
		MeshVertex v1;
		MeshVertex v2;

	public:
		MeshFace();
		MeshFace(const MeshFace& o);
		MeshFace& operator= (const MeshFace& o);

		void addVertexBoneAssignment(short index, int vba);
		void addVertex(short index, float *v);
		void addNormal(short index, short *v);
		void addColour(short index, Ogre::uint col);
		void addUvCord(short index, int layer, float *uv);
		void addIndex(short index, int real);
		void setMaxLayer(int lay);

		void calcNormal();
	};


	
	inline MeshFace::MeshFace()
	{
	}


	
	inline MeshFace::MeshFace(const MeshFace& o)
	{
		*this= o;
	}


	
	inline MeshFace& MeshFace::operator= (const MeshFace& o)
	{
		v0= o.v0;
		v1= o.v1;
		v2= o.v2;
		return *this;
	}


	
	inline void MeshFace::calcNormal()
	{
		Ogre::Vector3 vr0= Ogre::Vector3(v0.vertex);
		Ogre::Vector3 vr1= Ogre::Vector3(v1.vertex);
		Ogre::Vector3 vr2= Ogre::Vector3(v2.vertex);

		Ogre::Vector3 n= (vr1 - vr2).crossProduct(vr2 - vr0);
		if (n.length() > 0)
			n.normalise();

		/// set for the curface
		VEC3CPY(v0.normal, n);
		VEC3CPY(v1.normal, n);
		VEC3CPY(v2.normal, n);
	}


	
	inline void MeshFace::addVertexBoneAssignment(short index, int vba)
	{
		switch (index)
		{
		case 0:
			v0.vba_index= vba;
			break;
		case 1:
			v1.vba_index= vba;
			break;
		case 2:
			v2.vba_index= vba;
			break;
		}
	}

	//add vertex position 
	inline void MeshFace::addVertex(short index, float* v)
	{
		switch (index)
		{
		case 0:
			VEC3CPY(v0.vertex, v);
			break;
		case 1:
			VEC3CPY(v1.vertex, v);
			break;
		case 2:
			VEC3CPY(v2.vertex, v);
			break;
		}
	}

	
	inline void MeshFace::addNormal(short index, short *v)
	{
		switch (index)
		{
		case 0:
			VEC3CPN(v0.normal, v);
			break;
		case 1:
			VEC3CPN(v1.normal, v);
			break;
		case 2:
			VEC3CPN(v2.normal, v);
			break;
		}
	}

	
	inline void MeshFace::addColour(short index, Ogre::uint col)
	{
		switch (index)
		{
		case 0:
			v0.colour= col;
			break;
		case 1:
			v1.colour= col;
			break;
		case 2:
			v2.colour= col;
			break;
		}
	}

	
	inline void MeshFace::addUvCord(short index, int layer, float* uv)
	{
		if (layer >= 0 && layer < 8)
		{
			switch (index)
			{
			case 0:
				VEC2CPY(v0.uv[layer], uv);
				break;
			case 1:
				VEC2CPY(v1.uv[layer], uv);
				break;
			case 2:
				VEC2CPY(v2.uv[layer], uv);
				break;
			}
		}
	}

	
	inline void MeshFace::addIndex(short index, int real)
	{
		switch (index){
		case 0:
			v0.index= real;
			break;
		case 1:
			v1.index= real;
			break;
		case 2:
			v2.index= real;
			break;
		}
	}

	
	inline void MeshFace::setMaxLayer(int lay)
	{
		v0.layer_max= v1.layer_max= v2.layer_max= lay;
	}


	
	inline MeshFaceIndex::MeshFaceIndex()
	{
		v1= v2= v3= 0;
	}


	
	inline MeshFaceIndex::MeshFaceIndex(const MeshFaceIndex& o)
	{
		*this= o;
	}

	
	inline MeshFaceIndex& MeshFaceIndex::operator= (const MeshFaceIndex& o)
	{
		v1= o.v1;
		v2= o.v2;
		v3= o.v3;
		return *this;
	}
}

#endif

